home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
C
/
Frameworks
/
Recursive Shell 1.0.1
/
Examples
/
ListFiles ƒ
/
SearchFolder.c
< prev
next >
Wrap
Text File
|
1996-06-17
|
6KB
|
257 lines
/********************************************************************************/
//
// Folder Searching Routines
//
// Based on code supplied by Andrew Duncan
//
// Version 1.0.1
//
// Created: 13 May 1996
// Modified: 17 June 1996
//
/********************************************************************************/
#include "Main.h"
#include "DoStuff.h"
#include "SearchFolder.h"
#include "DialogUtil.h"
#include "Utility.h"
// kTimeOut defines how much time (in ticks) the program is willing to wait for
// other programs to get events while it's stepping though the folders/files.
// To make the program more multifinder-friendly, make the number bigger. The
// downside to this is that the program slows down, especially while in the
// background.
// To speed things up, make the number smaller. This will slow down background
// applications. If you go too far, they will become sluggish, and when you
// switch to, say, the Finder while the program is working, you will become
// frustrated at how long you have to wait for your clicks to register and
// whatnot.
#define kTimeOut 3
// Globals
static short sInputVRefNum;
// Prototypes
Boolean FSSpecToDirID( FSSpec dirSpec, long* dirID );
static OSErr ReadDir( long dirID, short dirIndex,
FSSpec* theSpec, Boolean* isDirectory, long* itsDirID );
Boolean RecursiveReadDir( long dirID );
Boolean WorkingEvent( EventRecord event );
Boolean WorkingMenu( long menuChoice );
//
// DoAllFiles
//
void DoAllFiles( FSSpec startSpec )
{
long dirID;
if ( FSSpecToDirID( startSpec, &dirID ) )
RecursiveReadDir( dirID );
else
DisplayAlert( "\pERROR: Problem processing selected folder name" );
}
//
// FSSpecToDirID
//
// Takes the FSSpec of a directory and returns a DirID to it.
// Works by creating a FSSpec for a (probably) non-existant file in that
// directory named "?" and grabbing the ParID field of the new FSSpec.
// Returns True if successful in getting the directory ID, false otherwise.
//
// Andy sez:
// Should change to just use the ioDrDirID returned by PBGetCatInfo!!!
Boolean FSSpecToDirID( FSSpec dirSpec, long* dirID )
{
FSSpec newSpec;
OSErr err;
char nameLength, i;
sInputVRefNum = dirSpec.vRefNum;
if ( IsAFolder( &dirSpec ) )
{
nameLength = dirSpec.name[0]; // Get the length of directory name
// Shift the name one character to the right:
i = nameLength + 1;
while ( i > 1 )
{
dirSpec.name[i] = dirSpec.name[i - 1];
i--;
}
dirSpec.name[1] = ':'; // Make it a partial pathname
dirSpec.name[nameLength + 2] = ':'; // Append a colon
dirSpec.name[nameLength + 3] = '?'; // An unlikely filename
dirSpec.name[0] += 3; // Fix the length byte for additions
// Make an FSSpec for the new filename and get the parent ID from it:
err = FSMakeFSSpec( dirSpec.vRefNum, dirSpec.parID, dirSpec.name, &newSpec );
if ( ( err == noErr ) || ( err == fnfErr ) )
{
*dirID = newSpec.parID;
return ( true );
}
else
return ( false );
}
else
return ( false );
}
//
// ReadDir
//
static OSErr ReadDir( long dirID, short dirIndex, // Input
FSSpec* theSpec, Boolean* isDirectory, long* itsDirID ) // Output
{
CInfoPBRec pb;
OSErr err;
pb.hFileInfo.ioCompletion = (IOCompletionUPP) NULL;
pb.hFileInfo.ioNamePtr = theSpec->name;
pb.hFileInfo.ioVRefNum = sInputVRefNum; // DANGER! NEVER SET!
pb.hFileInfo.ioFDirIndex = dirIndex; // Find out about nth file
pb.hFileInfo.ioDirID = dirID;
err = PBGetCatInfo( &pb, false );
if ( err == noErr )
{
err = FSMakeFSSpec(sInputVRefNum, dirID, pb.hFileInfo.ioNamePtr, theSpec);
*isDirectory = pb.hFileInfo.ioFlAttrib & (1 << 4);
if (*isDirectory) *itsDirID = pb.dirInfo.ioDrDirID;
return noErr;
}
else
return err;
}
//
// RecursiveReadDir
// This is the routine which recurses folder to folder, handing off file/folder
// info to the routines in DoStuff.c
// The routine returns true when it has finished the folder it is doing normally,
// false when it is aborted.
//
Boolean RecursiveReadDir( long dirID )
{
FSSpec theSpec;
OSErr err = noErr;
short dirIndex = 1; // What item in the dir to look at - start with 1
Boolean isDirectory;
long itsDirID;
EventRecord event;
while ( err == noErr )
{
BusyCursor(); // Set the cursor to the watch to show we're doing something.
// Be a good citizen and let other applications get some processor time,
// also check for command-period (abort) at the same time:
if ( WaitNextEvent( keyDownMask + mDownMask, &event, kTimeOut, nil ) )
{
if ( !( WorkingEvent( event ) ) )
return( false );
}
err = ReadDir( dirID, dirIndex, &theSpec, &isDirectory, &itsDirID );
if ( err == noErr )
{
if ( isDirectory )
{
if ( !( RecursiveReadDir( itsDirID ) ) ) // Recurse into the directory
{
SetCursor(&(qd.arrow)); // Set the cursor back to the arrow.
return ( false ); // Abort.
}
DoToEachFolder( theSpec );
}
else
DoToEachFile( theSpec );
dirIndex++; // Move on to the next item
}
}
return ( true );
}
//
// WorkingEvent
// A little mini event handler to detect if the user wants to abort while the
// program is working.
//
Boolean WorkingEvent( EventRecord event )
{
WindowPtr window;
long menuChoice;
char theChar;
short thePart;
switch ( event.what )
{
case mouseDown:
thePart = FindWindow( event.where, & window );
switch ( thePart )
{
case inMenuBar:
menuChoice = MenuSelect( event.where );
if ( !( WorkingMenu( menuChoice ) ) )
return ( false );
break;
case inSysWindow:
SystemClick( &event, window );
break;
}
break;
case keyDown:
case autoKey:
if ( event.modifiers & cmdKey ) // Is the command key pressed?
{
theChar = event.message & charCodeMask;
menuChoice = MenuKey( theChar );
if ( !( WorkingMenu( menuChoice ) ) )
return ( false );
}
break;
}
return( true );
}
//
// WorkingMenu
// A little mini menu handler to detect if the user wants to abort while the
// program is working.
//
Boolean WorkingMenu( long menuChoice )
{
short menu, item;
menu = HiWord( menuChoice );
item = LoWord( menuChoice );
if ( ( menu == mFile ) && ( item == iOpen ) ) // The Abort item.
return( false );
else
{
HandleMenuChoice( menuChoice ); // Let the main menu procedure deal with it
return( true ); // Keep on working
}
}